-- jeli istnieje tabela w bazie ...
IF OBJECT_ID('dbo.Organizacja') IS NOT NULL
	DROP TABLE dbo.Organizacja;   -- ... to jest usuwana
GO

-- tworzymy now tabel
CREATE TABLE dbo.Organizacja
(
	id        INT PRIMARY KEY IDENTITY(1,1),
	nazwa     VARCHAR(50),
	parent_id INT   -- kolumna wskazujca rodzica danego elementu
);
GO

-- wstawianie danych do tabeli
-- najpierw wstawiany jest element bdcy na wierzchoku hierarchii
INSERT INTO dbo.Organizacja VALUES ('Polska', 0);
-- nastepnie wstawiane s elementy podlegajce pod rodzica Polska
INSERT INTO dbo.Organizacja VALUES ('woj. lubelskie', 1);
INSERT INTO dbo.Organizacja VALUES ('woj. mazwieckie', 1);
INSERT INTO dbo.Organizacja VALUES ('woj. lskie', 1);
INSERT INTO dbo.Organizacja VALUES ('woj. podlaskie', 1);
-- nastepne wstawiane s elementy, ktrych rodzicami s wojewdztwa
INSERT INTO dbo.Organizacja VALUES ('Lublin', 2);
INSERT INTO dbo.Organizacja VALUES ('ukw', 2);
INSERT INTO dbo.Organizacja VALUES ('Warszawa', 3);
INSERT INTO dbo.Organizacja VALUES ('Siedlce', 3);
INSERT INTO dbo.Organizacja VALUES ('Katowice', 4);
INSERT INTO dbo.Organizacja VALUES ('Zabrze', 4);
INSERT INTO dbo.Organizacja VALUES ('Ruda lska', 4);
INSERT INTO dbo.Organizacja VALUES ('Biaystok', 5);


IF OBJECT_ID('dbo.Czas') IS NOT NULL
	DROP TABLE dbo.Czas;
GO

-- definiowanie nowej tabeli
CREATE TABLE dbo.Czas
(
	id      INT PRIMARY KEY IDENTITY(1,1),
	miesiac VARCHAR(11),
	rok     INT
);
GO

-- wstawienie danych
INSERT INTO dbo.Czas VALUES ('stycze', 2007);
INSERT INTO dbo.Czas VALUES ('luty', 2007);
INSERT INTO dbo.Czas VALUES ('marzec', 2007);
INSERT INTO dbo.Czas VALUES ('kwiecie', 2007);
INSERT INTO dbo.Czas VALUES ('maj', 2007);
INSERT INTO dbo.Czas VALUES ('czerwiec', 2007);
INSERT INTO dbo.Czas VALUES ('lipiec', 2007);
INSERT INTO dbo.Czas VALUES ('sierpie', 2007);
INSERT INTO dbo.Czas VALUES ('wrzesie', 2007);
INSERT INTO dbo.Czas VALUES ('paxdziernik', 2007);
INSERT INTO dbo.Czas VALUES ('listopad', 2007);
INSERT INTO dbo.Czas VALUES ('grudzie', 2007);


IF OBJECT_ID('dbo.Fakty') IS NOT NULL
	DROP TABLE dbo.Fakty;
GO

CREATE TABLE dbo.Fakty
(
	czas_id INT,  -- identyfikator czasu z tabeli Czas
	org_id  INT,  -- identyfikator MPK-u
	zasob   VARCHAR(50),  -- rodzaj zasobu
	zmienna VARCHAR(30),  -- informacja jakiego rodzaju dane s przechowywane
	ilosc INT             -- wielko tych danych
);
GO


-- zasoby osobowe - dyrektorzy
INSERT INTO dbo.Fakty VALUES (1, 6, 'dyrektor', 'zasoby osobowe', 2);
INSERT INTO dbo.Fakty VALUES (1, 7, 'dyrektor', 'zasoby osobowe', 1);
INSERT INTO dbo.Fakty VALUES (1, 8, 'dyrektor', 'zasoby osobowe', 7);
INSERT INTO dbo.Fakty VALUES (1, 9, 'dyrektor', 'zasoby osobowe', 4);
INSERT INTO dbo.Fakty VALUES (1, 10, 'dyrektor', 'zasoby osobowe', 1);
INSERT INTO dbo.Fakty VALUES (1, 11, 'dyrektor', 'zasoby osobowe', 5);
INSERT INTO dbo.Fakty VALUES (1, 12, 'dyrektor', 'zasoby osobowe', 3);
INSERT INTO dbo.Fakty VALUES (1, 13, 'dyrektor', 'zasoby osobowe', 3);
-- zasoby osobowe - kierownicy
INSERT INTO dbo.Fakty VALUES (1, 6, 'kierownik', 'zasoby osobowe', 4);
INSERT INTO dbo.Fakty VALUES (1, 7, 'kierownik', 'zasoby osobowe', 2);
INSERT INTO dbo.Fakty VALUES (1, 8, 'kierownik', 'zasoby osobowe', 14);
INSERT INTO dbo.Fakty VALUES (1, 9, 'kierownik', 'zasoby osobowe', 8);
INSERT INTO dbo.Fakty VALUES (1, 11, 'kierownik', 'zasoby osobowe', 10);
INSERT INTO dbo.Fakty VALUES (1, 12, 'kierownik', 'zasoby osobowe', 6);
INSERT INTO dbo.Fakty VALUES (1, 13, 'kierownik', 'zasoby osobowe', 6);
-- zasoby osobowe  pozostali pracownicy
INSERT INTO dbo.Fakty VALUES (1, 6, 'pozostali', 'zasoby osobowe', 20);
INSERT INTO dbo.Fakty VALUES (1, 7, 'pozostali', 'zasoby osobowe', 10);
INSERT INTO dbo.Fakty VALUES (1, 8, 'pozostali', 'zasoby osobowe', 70);
INSERT INTO dbo.Fakty VALUES (1, 9, 'pozostali', 'zasoby osobowe', 40);
INSERT INTO dbo.Fakty VALUES (1, 10, 'pozostali', 'zasoby osobowe', 10);
INSERT INTO dbo.Fakty VALUES (1, 11, 'pozostali', 'zasoby osobowe', 50);
INSERT INTO dbo.Fakty VALUES (1, 12, 'pozostali', 'zasoby osobowe', 30);

-- samochody, jakie zostay przydzielone poszczeglnym MPK
INSERT INTO dbo.Fakty VALUES (1, 6, 'samochody', 'zasoby rzeczowe', 7);
INSERT INTO dbo.Fakty VALUES (1, 7, 'samochody', 'zasoby rzeczowe', 4);
INSERT INTO dbo.Fakty VALUES (1, 8, 'samochody', 'zasoby rzeczowe', 17);
INSERT INTO dbo.Fakty VALUES (1, 9, 'samochody', 'zasoby rzeczowe', 10);
INSERT INTO dbo.Fakty VALUES (1, 10, 'samochody', 'zasoby rzeczowe', 6);
INSERT INTO dbo.Fakty VALUES (1, 11, 'samochody', 'zasoby rzeczowe', 10);
INSERT INTO dbo.Fakty VALUES (1, 12, 'samochody', 'zasoby rzeczowe', 7);
INSERT INTO dbo.Fakty VALUES (1, 13, 'samochody', 'zasoby rzeczowe', 8);

-- wolumeny, wg ktrych naley alokowa samochody 
-- wolumeny dla dyrektorw
INSERT INTO dbo.Fakty VALUES (1, 6, 'dyrektor', 'wolumen samochodu', 1);
INSERT INTO dbo.Fakty VALUES (1, 9, 'dyrektor', 'wolumen samochodu', 4);
INSERT INTO dbo.Fakty VALUES (1, 10, 'dyrektor', 'wolumen samochodu', 1);
INSERT INTO dbo.Fakty VALUES (1, 11, 'dyrektor', 'wolumen samochodu', 5);
INSERT INTO dbo.Fakty VALUES (1, 12, 'dyrektor', 'wolumen samochodu', 3);
INSERT INTO dbo.Fakty VALUES (1, 13, 'dyrektor', 'wolumen samochodu', 3);
-- wolumeny dla kierownikw
INSERT INTO dbo.Fakty VALUES (1, 6, 'kierownik', 'wolumen samochodu', 3);
INSERT INTO dbo.Fakty VALUES (1, 9, 'kierownik', 'wolumen samochodu', 8);
INSERT INTO dbo.Fakty VALUES (1, 11, 'kierownik', 'wolumen samochodu', 10);
INSERT INTO dbo.Fakty VALUES (1, 12, 'kierownik', 'wolumen samochodu', 6);
INSERT INTO dbo.Fakty VALUES (1, 13, 'kierownik', 'wolumen samochodu', 1);
-- wolumeny dla pozostaych pracownikws
INSERT INTO dbo.Fakty VALUES (1, 6, 'pozostali', 'wolumen samochodu', 6);
INSERT INTO dbo.Fakty VALUES (1, 9, 'pozostali', 'wolumen samochodu', 40);
INSERT INTO dbo.Fakty VALUES (1, 10, 'pozostali', 'wolumen samochodu', 10);
INSERT INTO dbo.Fakty VALUES (1, 11, 'pozostali', 'wolumen samochodu', 3);
INSERT INTO dbo.Fakty VALUES (1, 12, 'pozostali', 'wolumen samochodu', 4);

-- jeli w bazie istnieje procedura o identycznej nazwie
IF OBJECT_ID('dbo.alokacja_samochodow') IS NOT NULL
	DROP PROCEDURE dbo.alokacja_samochodow; -- to j usuwamy
GO

-- tworzymy now procedur
CREATE PROCEDURE dbo.alokacja_samochodow 
AS
BEGIN

	---------------- krok 1 ----------------
	-- Usunicie rekordw (jeli istniej) mwicych ile samochodw zostao
-- przypisanych dyrektorom, kierownikom, i pozostaym pracownikom
-- Krok jest wymagany, jeli procedura ma by uruchamiana wicej ni jeden raz.
	DELETE FROM dbo.Fakty WHERE zmienna IN ('Samochody Dyrektorw', 'Samochody 
Kierownikw', 'Samochody Pozostaych');

	---------------- krok 2 ----------------
-- Stworzenie tabeli przechowujcej w kadym z wierszy informacje na temat
-- iloci dyrektorw, kierownikw i pozostaych pracownikw pracujcych w danym 
-- MPK i danym okresie. Do stworzenia tabeli uyto instrukcji SELECT INTO  jest to 
-- instrukcja nielogowana, dziki czemu jest bardzo szybka.
	IF OBJECT_ID('dbo.zasoby_tmp') IS NOT NULL
		DROP TABLE dbo.zasoby_tmp;

	SELECT 
		f.czas_id,
		f.org_id,
		ISNULL((SELECT a.ilosc
		FROM dbo.Fakty a 
		WHERE f.czas_id = a.czas_id AND 
				f.org_id = a.org_id AND 
				a.zasob = 'dyrektor' AND
				a.zmienna = 'zasoby osobowe'), 0) AS dyrektorzy,
		ISNULL((SELECT a.ilosc
		FROM dbo.Fakty a 
		WHERE f.czas_id = a.czas_id AND 
				f.org_id = a.org_id AND 
				a.zasob = 'kierownik' AND
				a.zmienna = 'zasoby osobowe'), 0) AS kierownicy,
		ISNULL((SELECT a.ilosc
		FROM dbo.Fakty a 
		WHERE f.czas_id = a.czas_id AND 
				f.org_id = a.org_id AND 
				a.zasob = 'pozostali' AND
				a.zmienna = 'zasoby osobowe'), 0) AS pozostali,
		ilosc AS samochody
	INTO dbo.zasoby_tmp
	FROM dbo.Fakty f
	WHERE f.zmienna = 'zasoby rzeczowe'

	---------------- krok 3 ----------------
-- Stworzenie nowej tabeli na podstawie zasoby_tmp, do ktrej dodane zostan 
-- informacje o wolumenach  jak maj by alokowane samochody w poszczeglnych MPK
	IF OBJECT_ID('dbo.wolumeny_i_zasoby_tmp') IS NOT NULL
		DROP TABLE dbo.wolumeny_i_zasoby_tmp;

	SELECT
		z.czas_id,
		z.org_id,
		z.dyrektorzy,
		z.kierownicy,
		z.pozostali,
		(SELECT a.ilosc
		FROM dbo.Fakty a 
		WHERE z.czas_id = a.czas_id AND 
				z.org_id = a.org_id AND 
				a.zasob = 'dyrektor' AND
				a.zmienna = 'wolumen samochodu') AS wolumen_dyr,
		(SELECT a.ilosc
		FROM dbo.Fakty a 
		WHERE z.czas_id = a.czas_id AND 
				z.org_id = a.org_id AND 
				a.zasob = 'kierownik' AND
				a.zmienna = 'wolumen samochodu') AS wolumen_kier,
		(SELECT a.ilosc
		FROM dbo.Fakty a 
		WHERE z.czas_id = a.czas_id AND 
				z.org_id = a.org_id AND 
				a.zasob = 'pozostali' AND
				a.zmienna = 'wolumen samochodu') AS wolumen_poz,
		z.samochody
	INTO dbo.wolumeny_i_zasoby_tmp
	FROM dbo.zasoby_tmp z

---------------- krok 4 ----------------
-- Przypisanie samochodw do dyrektorw. 
	IF OBJECT_ID('dbo.samochody_dla_dyr') IS NOT NULL
		DROP TABLE dbo.samochody_dla_dyr;

	SELECT
		czas_id,
		org_id,
		dyrektorzy,
		kierownicy,
		pozostali,
		wolumen_dyr,
		wolumen_kier,
		wolumen_poz,
		samochody,
		CASE
-- jeli nie ma dyrektorw w danym MPK, to nie jest przypisywany aden samochod
			WHEN dyrektorzy = 0 THEN 0
		-- jeli w danym MPK s sami dyrektorzy, to przypisujemy im wszystkie samochody
			WHEN (dyrektorzy > 0) AND (kierownicy = 0) AND (pozostali = 0) 
THEN samochody
		-- jeli wolumen dla dyrektorw jest mniejszy lub rwny liczbie samochodw, to
		-- przypisujemy ilo wskazan w wolumenie
			WHEN (wolumen_dyr IS NOT NULL) AND (wolumen_dyr <= samochody) 
THEN wolumen_dyr
-- jeli wolumen dla dyrektorw jest wikszy ni liczba samochodw, to
		-- przypisujemy wszystkie samochody
			WHEN (wolumen_dyr IS NOT NULL) AND (wolumen_dyr > samochody) 
THEN samochody
		-- jeli nie przypisano wolumenu i liczba samochodow jest wiksza ni
		-- liczba dyrektorw, to przypisujemy po 1 samochodzie dla dyrektora
			WHEN (wolumen_dyr IS NULL) AND (dyrektorzy <= samochody) 
THEN dyrektorzy
		-- jeli nie przypisano wolumenu i liczba samochodow jest mniejsza ni
		-- liczba dyrektorw, to przypisujemy wszystkie samochody dyrektorom
			WHEN (wolumen_dyr IS NULL) AND (dyrektorzy > samochody) 
THEN samochody
		END AS samochody_dla_dyr,
-- obliczamy ile samochodw zostao do rozalokowania na kierownikw i pozostaych
-- pracownikw
		samochody -
		(CASE
			WHEN dyrektorzy = 0 THEN 0
			WHEN (dyrektorzy > 0) AND (kierownicy = 0) AND (pozostali = 0) 
THEN samochody
			WHEN (wolumen_dyr IS NOT NULL) AND (wolumen_dyr <= samochody) 
THEN wolumen_dyr
			WHEN (wolumen_dyr IS NOT NULL) AND (wolumen_dyr > samochody) 
THEN samochody
			WHEN (wolumen_dyr IS NULL) AND (dyrektorzy <= samochody) 
THEN dyrektorzy
			WHEN (wolumen_dyr IS NULL) AND (dyrektorzy > samochody) 
THEN samochody
		END) AS samochody_do_rozalokowania
	INTO dbo.samochody_dla_dyr
	FROM dbo.wolumeny_i_zasoby_tmp

---------------- krok 5 ----------------
-- Przypisanie samochodw do kierownikw i pozostaych pracownikw. 
-- Alokacja odbywa si podobnie jak w kroku 4
	IF OBJECT_ID('dbo.samochody_dla_dyr_kier_i_poz') IS NOT NULL
		DROP TABLE dbo.samochody_dla_dyr_kier_i_poz;

	SELECT
		czas_id,
		org_id,
		dyrektorzy,
		kierownicy,
		pozostali,
		wolumen_dyr,
		wolumen_kier,
		wolumen_poz,
		samochody,
		samochody_do_rozalokowania,
		samochody_dla_dyr,
		CASE
			WHEN kierownicy = 0 THEN 0
			WHEN (kierownicy > 0) AND (pozostali = 0) THEN 
samochody_do_rozalokowania
			WHEN (wolumen_kier IS NOT NULL) AND (wolumen_kier <= 
samochody_do_rozalokowania) THEN wolumen_kier
			WHEN (wolumen_kier IS NOT NULL) AND (wolumen_kier > 
samochody_do_rozalokowania) THEN samochody_do_rozalokowania
			WHEN (wolumen_kier IS NULL) AND (kierownicy <= 
samochody_do_rozalokowania) THEN kierownicy
			WHEN (wolumen_kier IS NULL) AND (kierownicy > 
samochody_do_rozalokowania) THEN samochody_do_rozalokowania
		END AS samochody_dla_kier,
		samochody_do_rozalokowania -
		(CASE
			WHEN kierownicy = 0 THEN 0
			WHEN (kierownicy > 0) AND (pozostali = 0) THEN 
samochody_do_rozalokowania
			WHEN (wolumen_kier IS NOT NULL) AND (wolumen_kier <= 
samochody_do_rozalokowania) THEN wolumen_kier
			WHEN (wolumen_kier IS NOT NULL) AND (wolumen_kier > 
samochody_do_rozalokowania) THEN samochody_do_rozalokowania
			WHEN (wolumen_kier IS NULL) AND (kierownicy <= 
samochody_do_rozalokowania) THEN kierownicy
			WHEN (wolumen_kier IS NULL) AND (kierownicy > 
samochody_do_rozalokowania) THEN samochody_do_rozalokowania
		END) AS samochody_dla_poz
	INTO dbo.samochody_dla_dyr_kier_i_poz
	FROM dbo.samochody_dla_dyr

 ---------------- krok 6 ----------------
 -- Wstawienie rozalokowanych danych do tabeli faktw
	INSERT INTO dbo.FAKTY	
	SELECT
		czas_id,
		org_id,
		'Samochody' AS zasob,
		'Samochody Dyrektorw' AS zmienna,
		samochody_dla_dyr AS ilosc
	FROM dbo.samochody_dla_dyr_kier_i_poz
	UNION ALL
	SELECT
		czas_id,
		org_id,
		'Samochody' AS zasob,
		'Samochody Kierownikw' AS zmienna,
		samochody_dla_kier AS ilosc
	FROM dbo.samochody_dla_dyr_kier_i_poz
	UNION ALL
	SELECT
		czas_id,
		org_id,
		'Samochody' AS zasob,
		'Samochody Pozostaych' AS zmienna,
		samochody_dla_poz AS ilosc
	FROM dbo.samochody_dla_dyr_kier_i_poz

---------------- krok 7 ----------------
-- Usunicie zbdnych tabel tymczasowych
	IF OBJECT_ID('dbo.zasoby_tmp') IS NOT NULL
		DROP TABLE dbo.zasoby_tmp;
	IF OBJECT_ID('dbo.wolumeny_i_zasoby_tmp') IS NOT NULL
		DROP TABLE dbo.wolumeny_i_zasoby_tmp;
	IF OBJECT_ID('dbo.samochody_dla_dyr') IS NOT NULL
		DROP TABLE dbo.samochody_dla_dyr;
	IF OBJECT_ID('dbo.samochody_dla_dyr_kier_i_poz') IS NOT NULL
		DROP TABLE dbo.samochody_dla_dyr_kier_i_poz;
-- koniec procedury
END;


exec alokacja_samochodow;
